﻿package com.qz.tool;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class CreatEntity {

	private static final String driver = "com.mysql.jdbc.Driver";

	private static final String url = "jdbc:mysql://10.0.1.90:3306/accounting-db?useUnicode=true&amp;characterEncoding=UTF-8";

	private static final String user = "root";

	private static final String pwd = "qian360";

	private static Connection conn = null;

	private CreatEntity() {
	}

	public static void main(String[] args) {
		try {
			System.out.println(getColumnFromTable("RESULT"));
			List<Object> tables = getAllTableName();
			for (Object tblName : tables) {
				String name = String.valueOf(tblName);
				String destPath = "D:\\zzz-bak\\mysql-entity\\" + formatName(name, true) + ".java";
				createEneityClass("com.qz.tool", name, true, destPath);
				System.out.println("映射对象已生成");
			}
		} catch (ClassNotFoundException | SQLException | IOException e) {
			e.printStackTrace();
		}
	}

	public static Connection getConnection() throws ClassNotFoundException, SQLException {
		if (conn == null) {
			Class.forName(driver);
			conn = DriverManager.getConnection(url, user, pwd);
			System.out.println("数据库已连接");
		}
		return conn;
	}

	public static void query(String sql) throws ClassNotFoundException, SQLException {
		conn = getConnection();
		PreparedStatement ps = conn.prepareStatement(sql);
		ResultSet rs = ps.executeQuery();
		while (rs.next()) {
			System.out.println(rs.getString(1));
		}
	}

	public static List<Object> getAllTableName() throws ClassNotFoundException, SQLException {
		conn = getConnection();
		List<Object> tables = new ArrayList<>();
		DatabaseMetaData metaData = conn.getMetaData();
		String[] types = { "TABLE" };
		ResultSet rs = metaData.getTables(null, null, null, types);
		while (rs.next()) {
			tables.add(rs.getObject("TABLE_NAME"));
		}
		return tables;
	}

	public static List<Column> getColumnFromTable(String tableName) throws ClassNotFoundException, SQLException {
		conn = getConnection();
		ResultSet rs = conn.getMetaData().getColumns(null, "%", tableName, "%");
		List<Column> result = new ArrayList<Column>();
		while (rs.next()) {
			// FROM:http://blog.csdn.net/uikoo9/article/details/39926687
			Column c = new Column();
			c.setName(rs.getString("COLUMN_NAME"));
			c.setType(rs.getString("TYPE_NAME"));
			c.setAutoincrement(rs.getString("IS_AUTOINCREMENT").equals("YES") ? true : false);
			c.setRemark(rs.getString("REMARKS"));
			result.add(c);
		}
		return result;
	}

	public static void writeFile(String str, String destPath) throws IOException {
		FileOutputStream out = null;
		out = new FileOutputStream(new File(destPath), true);
		out.write(str.getBytes("UTF-8"));
		out.close();
	}

	public static String getColumnTypeRelation(String type) {
		if (ColumnType.BIGINT.equals(type)) {
			return DataType.LONG;
		} else if (ColumnType.DOUBLE.equals(type)) {
			return DataType.DOUBLE;
		} else if (ColumnType.DATETIME.equals(type)) {
			return DataType.DATETIME;
		} else if (ColumnType.INT.equals(type)) {
			return DataType.INTEGER;
		} else if (ColumnType.SMALLINT.equals(type)) {
			return DataType.INTEGER;
		} else if (ColumnType.VARCHAR.equals(type)) {
			return DataType.STRING;
		}
		return null;
	}

	/**
	 * 自动将数据库中的实体类映射成Entity
	 * 
	 * @param packageName
	 *            包名
	 * @param tableName
	 *            表名
	 * @param useAnnotation
	 *            是否启用注解
	 * @param destPath
	 *            目标路径
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 * @throws IOException
	 */
	public static void createEneityClass(String packageName, String tableName, boolean useAnnotation, String destPath)
			throws ClassNotFoundException, SQLException, IOException {
		List<Column> columns = getColumnFromTable(tableName);
		StringBuilder sb = new StringBuilder();
		// 包名
		sb.append("package " + packageName + ";\n\n");
		// 导包
		sb.append("import java.util.Date;\n\n");
		if (useAnnotation) {
			sb.append("import javax.persistence.*;\n\n");
		}
		// 创建class
		if (useAnnotation) {
			sb.append("@Entity\n");
			sb.append("@Table(name = \"" + tableName.toUpperCase() + "\")\n");
		}
		String formatTblName = formatName(tableName, true);
		sb.append("public class " + formatTblName + "{\n");
		writeFile(sb.toString(), destPath);
		for (Column c : columns) {
			String dataType = getColumnTypeRelation(c.getType());
			String remark = c.getRemark();
			String columnName = c.getName();
			String name = formatName(c.getName(), false);
			String upperName = formatName(c.getName(), true);
			boolean isAutoincrement = c.isAutoincrement();
			sb = new StringBuilder();
			// remark
			if (remark != null) {
				sb.append("\t/**\n");
				sb.append("\t *" + remark + "\n");
				sb.append("\t */\n");
			}
			// 注解
			if (useAnnotation) {
				// 自增
				if (isAutoincrement) {
					sb.append("\t@Id\n");
					sb.append("\t@Column(name = \"ID\")\n");
					sb.append("\t@GeneratedValue(strategy = GenerationType.AUTO)\n");
				} else {
					sb.append("\t@Column(name = \"" + columnName + "\")\n");
				}
			}
			sb.append("\tprivate ");
			sb.append(dataType + " ");
			sb.append(name + ";\n");
			// get、set
			sb.append("\tpublic " + dataType + " get" + upperName + "(){\n");
			sb.append("\t\treturn " + name + ";\n");
			sb.append("\t}\n");
			sb.append("\tpublic void set" + upperName + "(" + dataType + " " + name + "){\n");
			sb.append("\t\tthis." + name + " = " + name + ";\n");
			sb.append("\t}\n");
			writeFile(sb.toString(), destPath);
		}
		writeFile("}", destPath);
	}

	/**
	 * 将ColumnName按照驼峰命名法命名
	 * 
	 * @param name
	 * @param firstUpperCase
	 *            首字母是否大写
	 * @return
	 */
	public static String formatName(String name, Boolean firstUpperCase) {
		if (name.indexOf("_") != -1) {
			String[] split = name.split("_");
			String result = "";
			for (String str : split) {
				result += str.toLowerCase().substring(0, 1).toUpperCase() + str.toLowerCase().substring(1);
			}
			return firstUpperCase ? result : result.substring(0, 1).toLowerCase() + result.substring(1);
		}
		return firstUpperCase ? name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase()
				: name.toLowerCase();
	}

}
